const attempts = 20; // 最大尝试次数
const interval = 1000; // 每次间隔 ms
const duration = 1000; // 默认点击等待延时

const storePath = "data/store.json"
const runJS = settings.runJS || false;
const achievementMode = settings.achievementMode || true;
const starMode = settings.starMode || false;
const roomID = settings.room || "37135473336";
const starRoomName = settings.starRoomName || "碰碰墙";
const userAttempts = Number(settings.thisAttempts || "0");
const useFixedAttempts = userAttempts > 0;
const weekMaxExp = Number(settings.weekMaxExp || "4000");
const singleExp = Number(settings.singleExp || "270");
let weekTotal = initWeekTotal();

// 获取图片资源
function getImgMat(path) {
  return file.readImageMatSync('assets/' + path + '.png');
}

// 读取存档
function loadWeekData() {
  try {
    const t = file.readTextSync(storePath);
    return JSON.parse(t);
  } catch (_) {
    return null;
  }
}

// 保存存档
function saveWeekData(data) {
  file.writeTextSync(storePath, JSON.stringify(data));
}

// 初始化或更新 weekTotal
function initWeekTotal() {
  const stored = loadWeekData();
  const calculated = Math.ceil(weekMaxExp / singleExp);

  // 首次 OR 配置变化 → 重写
  if (
      !stored ||
      stored.weekMaxExp !== weekMaxExp ||
      stored.singleExp !== singleExp
  ) {
    const newData = {
      weekMaxExp,
      singleExp,
      weekTotal: calculated
    };
    saveWeekData(newData);
    return calculated;
  }

  return stored.weekTotal;
}

// 刷完一次 → 计数 -1
function decreaseWeekTotal() {
  const stored = loadWeekData();
  if (!stored) return;

  stored.weekTotal = Math.max(stored.weekTotal - 1, 0);
  saveWeekData(stored);
  weekTotal = stored.weekTotal;
}

// 查找文本
async function findText(text, x, y, w, h, textAttempts = attempts) {
  const searchText = text.toLowerCase();

  for (let i = 0; i < textAttempts; i++) {
    const captureRegion = captureGameRegion();
    const ro = RecognitionObject.ocr(x, y, w, h);
    const results = captureRegion.findMulti(ro);
    captureRegion.dispose();

    for (let j = 0; j < results.count; j++) {
      const region = results[j];
      if (region.isExist() && region.text.toLowerCase().includes(searchText)) {
        return region;
      }
    }

    await sleep(interval);
  }

  return null;
}

// 查找图片
async function findImage(imgMat, x, y, w, h, imgAttempts = attempts) {
  const searchImg = RecognitionObject.TemplateMatch(imgMat, x, y, w, h);

  for (let i = 0; i < imgAttempts; i++) {
    const captureRegion = captureGameRegion();
    const result = captureRegion.find(searchImg);
    captureRegion.dispose();

    if (result.isExist()) {
      return result;
    }

    await sleep(interval);
  }

  return null;
}

// 查找文本并点击
async function findTextAndClick(text, x, y, w, h, textAttempts = attempts) {
  const target = await findText(text, x, y, w, h, textAttempts);
  if (target) {
    await sleep(duration);
    target.click();
  } else {
    log.error("文本{text}查找失败", text);
  }
}

// 查找图片并点击
async function findImageAndClick(path, x, y, w, h, imgAttempts = attempts) {
  const imgMat = getImgMat(path);
  const target = await findImage(imgMat, x, y, w, h, imgAttempts);
  if (target) {
    await sleep(duration);
    target.click();
  } else {
    log.error("图标{path}查找失败", path);
  }
}

// 清除游玩数据
async function deleteSource() {
  if (achievementMode) {
    await sleep(duration);
    await genshin.returnMainUi();
    log.info("开始清除地图数据");
    await sleep(duration);
    keyPress("VK_B");
    await sleep(duration);
    await findTextAndClick("管理关卡", 960, 0, 960, 100);
    await findTextAndClick("管理", 960, 980, 960, 100);
    await findImageAndClick("check_box", 0, 0, 1480, 340);
    await findTextAndClick("删除",960, 980, 960, 100);
    await findTextAndClick("确认", 960, 600, 960, 400);
    await findTextAndClick("确认", 960, 600, 960, 400);
    log.info("数据清除完成");
    await sleep(duration);
    await genshin.returnMainUi();
  }
}

// 进入千星奇域的全部奇域页面
async function enterSourcePage() {
  // 1. 检测是否在房间内，在则退出
  const inRoom = await findText("房间", 1500, 0, 420, 500, 5);
  if (inRoom) {
    keyPress("VK_P");
    await sleep(duration);
    await findImageAndClick("exit_room", 960, 0, 960, 540);
    await findTextAndClick("确认", 960, 600, 960, 400);
    await genshin.returnMainUi();
    keyPress("VK_F6");
  } else {
    keyPress("VK_F6");
  }

  await sleep(duration);
}

// 进入千星奇域的收藏奇域页面
async function enterStarSourcePage() {
  // 1. 检测是否在房间内，在则退出
  const inRoom = await findText("房间", 1500, 0, 420, 500, 5);
  if (inRoom) {
    keyPress("VK_P");
    await sleep(duration);
    await findImageAndClick("exit_room", 960, 0, 960, 540);
    await findTextAndClick("确认", 960, 600, 960, 400);
    await genshin.returnMainUi();
    keyPress("VK_B");
  } else {
    keyPress("VK_F6");
    await sleep(duration);
    await findTextAndClick("收藏", 0, 850, 300, 230);
  }

  await sleep(duration);
}

// 创建关卡
async function createMap() {
  await findTextAndClick("搜索", 1320, 0, 600, 95);
  await findTextAndClick("搜索", 0, 120, 1920, 60);
  inputText(roomID);
  await sleep(1000);
  await findTextAndClick("搜索", 0, 120, 1920, 60);
  await sleep(duration);
  click(355, 365);
  await sleep(duration);
  while (true) {
    const result = await findText("房间", 960, 100, 960, 200, 2);
    if (result) {
      await sleep(duration);
      result.click();
      await sleep(duration);
      break;
    } else {
      const result2 = await findText("大厅", 960, 600, 960, 400, 2);
      if (result2) {
        result2.click();
        await sleep(duration);
      }
    }
  }
  await findText("开始游戏", 960, 540, 960, 540);
  click(770, 275);
  await sleep(duration);
}

// 从收藏创建关卡
async function createStarMap() {
  await findTextAndClick("搜索", 0, 0, 1920, 120);
  inputText(starRoomName);
  await sleep(1000);
  await findTextAndClick("搜索", 0, 0, 1920, 120);
  await sleep(duration);
  click(420, 830);
  await sleep(duration);
  while (true) {
    const result = await findText("房间", 960, 100, 960, 200, 2);
    if (result) {
      await sleep(duration);
      result.click();
      await sleep(duration);
      break;
    } else {
      const result2 = await findText("大厅", 960, 600, 960, 400, 2);
      if (result2) {
        result2.click();
        await sleep(duration);
      }
    }
  }
  await findText("开始游戏", 960, 540, 960, 540);
  click(770, 275);
  await sleep(duration);
}

// 游玩关卡
async function playMap() {
  const stored = loadWeekData();
  const leave = stored ? stored.weekTotal : weekTotal;
  const total = useFixedAttempts ? userAttempts : leave;

  if (starMode) {
    await createStarMap();
  } else {
    await createMap();
  }

  while (true) {
    await sleep(duration);
    const result = await findText("开始游戏", 960, 540, 960, 540, 5);
    if (result) {
      await sleep(duration);
      result.click();
      log.info("开始执行第{i}/{total}次奇域挑战", 1, total);
      await sleep(duration);
    } else {
      await sleep(duration);
      break;
    }
  }
  let firstOutputCount = 0;
  while (true) {
    const whiteText = await findText("空白处", 610, 950, 700, 60, 1);
    if (whiteText) {
      await sleep(duration);
      click(610, 950);
    }

    const result = await findText("返回大厅", 960, 540, 960, 540, 1);
    if (result) {
      await sleep(duration);
      result.click();
      await sleep(duration);
      if (!useFixedAttempts) {
        decreaseWeekTotal();
      }
      log.info("本次关卡结束");
      break;
    } else {
      const inRoom = await findText("房间", 1500, 0, 420, 500, 1);
      if (inRoom) {
        break;
      }
      if (firstOutputCount % 16 === 0) {
        log.info("等待本次关卡结束...");
      }
      firstOutputCount++;
      await sleep(interval);
    }
  }

  if (achievementMode) {
    await deleteSource();
  }

  for (let i = 1; i < total; i++) {
    const inRoom = await findText("房间", 1500, 0, 420, 500);
    if (inRoom) {
      await sleep(duration);
      keyPress("VK_P");
      await sleep(duration);
      while (true) {
        const result = await findText("开始游戏", 960, 540, 960, 540, 1);
        if (result) {
          await sleep(duration);
          result.click();
          log.info("开始执行第{i}/{total}次奇域挑战", i + 1, total);
          await sleep(duration);
          break;
        } else {
          await sleep(duration);
        }
      }
      let outputCount = 0;
      while (true) {
        const whiteText = await findText("空白处", 610, 950, 700, 60, 1);
        if (whiteText) {
          await sleep(duration);
          click(610, 950);
        }
        const result = await findText("返回大厅", 960, 540, 960, 540, 1);
        if (result) {
          await sleep(duration);
          result.click();
          await sleep(duration);
          if (!useFixedAttempts) {
            decreaseWeekTotal();
          }
          log.info("本次关卡结束");
          break;
        } else {
          const inRoom = await findText("房间", 1500, 0, 420, 500, 1);
          if (inRoom) {
            break;
          }
          if (outputCount % 10 === 0) {
            log.info("等待本次关卡结束...");
          }
          outputCount++;
          await sleep(interval);
        }
      }
      if (achievementMode) {
        await deleteSource();
      }
    }
  }
}

// 退出到提瓦特
async function exitToTeyvat() {
  await genshin.returnMainUi();
  await sleep(duration);
  keyPress("VK_F2");
  await sleep(duration);
  await findTextAndClick("返回", 960, 0, 960, 100);
  await sleep(duration);
  await findTextAndClick("确认", 960, 600, 960, 400);
}

(async function () {
  if (!runJS) {
    log.error("您未同意此脚本的免责声明，请先同意后重新运行此脚本！");
    return;
  }

  await genshin.returnMainUi();

  if (useFixedAttempts) {
    // 手动模式：忽略本周计数
    log.info(
        "已进入指定次数模式，本次将执行{count}次挑战（不计入周进度）",
        userAttempts
    );
  } else {
    // 每周模式
    const stored = loadWeekData();
    const leave = stored.weekTotal;
    const done = Math.ceil(weekMaxExp / singleExp) - leave;

    log.info(
        "本周共需刷取 {total} 次，已刷 {done} 次，剩余 {leave} 次",
        Math.ceil(weekMaxExp / singleExp),
        done,
        leave
    );
  }

  if (starMode) {
    log.info("已使用收藏模式");
    await enterStarSourcePage();
  } else {
    await enterSourcePage();
  }
  await playMap();
  await exitToTeyvat();
})();
